package easyroute

import (
	"reflect"

	"gitee.com/haodreams/golib/session"
	"github.com/gin-gonic/gin"
)

type Grouper interface {
	Root() string                                      //获取路由根路径
	SetRoot(root string)                               //设置路由根路径
	Size() int                                         //配置路由数量
	DefaultGateway(c *gin.Context)                     //默认网关入口
	SetHandleFunc(name string, f func(c *gin.Context)) //设置路由规则
	SetLoginPage(loginPage string)                     //设置登录页

	WithSession(auth func(*gin.Context) (session.Sessioner, error)) //设置认证规则
}

// 自动注册到GET,POST
func Register(rootPath string, g Grouper, e *gin.Engine) {
	g.SetRoot(rootPath)
	//自动注册到GET,POST

	t := reflect.TypeOf(g)
	v := reflect.ValueOf(g)
	for i := 0; i < t.NumMethod(); i++ {
		method := t.Method(i)
		name := method.Name
		// log.Println(name)
		if !(name[0] >= 'A' && name[0] <= 'Z') { //method.IsExported(){//
			continue
		}
		if method.Type.NumOut() != 0 {
			continue
		}
		if method.Type.NumIn() != 2 { //第一个参数是指针自己(this)
			continue
		}

		if name == "DefaultGateway" {
			continue
		}

		//性能较低时可考虑二级路由
		fn := v.Method(i)
		if fn.CanInterface() {
			f, ok := fn.Interface().(func(*gin.Context)) //不能使用别名 gin.HandlerFunc，否则会导致类型断言失败
			if ok {
				g.SetHandleFunc(name, f)
				// path := rootPath + name
				// e.GET(path, f)
				// e.POST(path, f)
			}
		}
	}
	e.GET(g.Root()+"*path", g.DefaultGateway)
	if g.Size() > 0 {
		e.POST(g.Root()+"*path", g.DefaultGateway)
	}
}

type Roler interface {
	AddPath(path string)
}

// 设置认证
func WithSession(g Grouper, cb func(*gin.Context) (session.Sessioner, error)) Grouper {
	g.WithSession(cb)
	return g
}

// 设置角色
func WithRole(g Grouper, role Roler) Grouper {
	role.AddPath(g.Root())
	return g
}

// 需要认证
func WithAuth(g Grouper, role Roler, cb func(*gin.Context) (session.Sessioner, error)) Grouper {
	WithRole(g, role)
	g.WithSession(cb)
	return g
}

// 设置登录页
func WithLogin(g Grouper, loginPage string, role Roler, cb func(*gin.Context) (session.Sessioner, error)) Grouper {
	g.SetLoginPage(loginPage)
	WithAuth(g, role, cb)
	return g
}
